home *** CD-ROM | disk | FTP | other *** search
/ Computer Music Interactif…cial Edition 1999 Winter / cd 3.iso / pc / Mac / Shares / Midishare™1.68 / Development Tools / Common Lisp / MCL_PPC / MidiShare.lisp next >
Encoding:
Text File  |  1996-09-09  |  43.0 KB  |  1,089 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;  MidiShare-interface.lisp
  3. ;;
  4. ;;  Copyright (c) 1990, GRAME.  All rights reserved.
  5. ;;
  6. ;;  This file contains definitions for records and Pascal style routines, used
  7. ;;  for interfacing ACL with MidiShare 1.31, real-time multitasking Midi operating system.
  8. ;;  It is in conformity with MPW Pascal MidiShareUnit.p .
  9. ;;
  10. ;;  History :
  11. ;;  
  12. ;;   11-Nov-90, First version. -Yo-
  13. ;;   25-Nov-90, Ajoute def de TMidiSeq + FirstEv & LastEv -Yo-
  14. ;;   25-Nov-90, Continue changé en Cont -Yo-
  15. ;;   26-Nov-90, Modification de firstEv, lastEv, link,
  16. ;;              on ne pouvais pas ecrire par ex: (firstEv seq nil) qui était 
  17. ;;              confondu avec (firstEv seq)
  18. ;;   01-Dec-90, Ajout d'une macro DOEVENTS, analogue à DOLIST, pour parcourir
  19. ;;              une chaine d'événements.-Yo-
  20. ;;              Ajout des fonctions : Clock, typeName, name, fieldslist,
  21. ;;              printEv, printSeq. -Yo-
  22. ;;              Ajout des fonctions ou macro : pushevent, dupevents, delevents,
  23. ;;              mergeevents. -Yo-
  24. ;;   07-Dec-90, Correction de ProgChange. -Yo-
  25. ;;   12-Dec-90  Ajout de linkSE,linkST
  26. ;;-------------------------------------------------------------------------
  27. ;;   15-Dec-90  Nouvelle version de l'interface, restreinte aux seules
  28. ;;              fonctions de MidiShare et utilisant des macros. -Yo- 
  29. ;;   09-Jan-91  Ajout d'une variante info dans la description d'un événement et des
  30. ;;              fonctions d'accès associées.
  31. ;;   09-Jan-91  Ajout fonctions d'acces aux filtres
  32. ;;   14-Mai-91  Adaptation MCL 2.0b1
  33. ;;   19-Mai-91  Pb des ff-call. Enrobage par (Block nil ..)
  34. ;;   22-Mai-91  Changement de nom des macro d'accès aux filtres
  35. ;;   31-Mai-91  Ajout des "s", (eval-when () ...)
  36. ;;   18-Jul-91  Ajout de la fonction bend (de l'ancienne version de msh-interface)
  37. ;;   04-Aou-91  Toutes les macros d'acces transferées dans le fichier extension
  38. ;;   31-Oct-91  Modification de MidiForgetTask
  39. ;;-------------------------------------------------------------------------
  40. ;;   04-Dec-94  Suppression du package MidiShare !!!
  41. ;;        Suppression des (block nil ..)
  42. ;;-------------------------------------------------------------------------
  43. ;;   22-07-96   Adaptation pour MCL PPC 3.9 : Le fonctionnement de ff-call a change
  44. ;;        pour les fonctions Pascal, il ne faut plus pusher dans la pile la place
  45. ;;        pour le resultat !!!
  46. ;;   23-07-96   Integration du fichiers "0 - quit-actions.lisp" et d'une partie du 
  47. ;;        fichier "2 - MidiShare-Extension.lisp"
  48.  
  49.  
  50. (eval-when (:compile-toplevel :load-toplevel :execute)
  51.   (let ((*warn-if-redefine* nil))
  52.     (require :ff)))
  53.  
  54.  
  55.  
  56.  
  57. ;;---------------------------------------------------------------------------------
  58. ;;
  59. ;;                 Utilities
  60. ;;
  61. ;;---------------------------------------------------------------------------------
  62.  
  63. (defun %%get-string (ps) 
  64.   "Same as %get-string but work with mac non-zone pointers"
  65.   (let (name count)
  66.     (setq count (%get-byte ps))
  67.     (setq name (make-string count))  
  68.     (dotimes (i count)
  69.       (setq ps (%inc-ptr ps 1))
  70.       (setf (aref name i) (coerce (%get-byte ps) 'character)))
  71.     name))
  72.  
  73. ;; For bug (?) in MCL PPC 3.9 when returning signed word
  74.  
  75. (defun %%unsigned-to-signed-word (w)
  76.   "convert an unsigned word to a signed word"
  77.   (if (< w 32768) w (- w 65536)))
  78.  
  79. (defun %%word-high-byte (w)
  80.   "most significant byte of a word"
  81.   (ash w -8))
  82.  
  83.  
  84. ;;---------------------------------------------------------------------------------
  85. ;;---------------------------------------------------------------------------------
  86. ;;
  87. ;;                 MidiShare Data Structures
  88. ;;
  89. ;;---------------------------------------------------------------------------------
  90. ;;---------------------------------------------------------------------------------
  91.  
  92.  
  93. ;; Extension record for typeSysEx events
  94.  
  95. (defrecord TMidiSEX  
  96.   (link (:pointer TMidiSEX))
  97.   (data (:array :byte 12)))
  98.  
  99.  
  100. ;; Extension record for typePrivate, typeProcess and typeDProcess events
  101.  
  102. (defrecord TMidiST
  103.   (ptr1 :pointer)
  104.   (ptr2 :pointer)
  105.   (ptr3 :pointer)
  106.   (ptr4 :pointer))
  107.  
  108.  
  109. ;;---------------------------------------------------------------------------------
  110. ;; Common Record for all MidiShare events
  111. ;;---------------------------------------------------------------------------------
  112.  
  113. (defrecord TMidiEv
  114.   (link (:pointer TMidiEv))
  115.   (date :longint)
  116.   (evtype :byte)
  117.   (ref :byte)
  118.   (port :byte)
  119.   (chan :byte)
  120.   (variant ((pitch :byte)
  121.             (vel :byte)
  122.             (dur :integer))
  123.            ((data0 :byte)
  124.             (data1 :byte)
  125.             (data2 :byte)
  126.             (data3 :byte))
  127.            ((info :longint))
  128.            ((linkSE (:pointer TMidiSEX)))
  129.            ((linkST (:pointer TMidiST)))))
  130.  
  131.  
  132. ;;---------------------------------------------------------------------------------
  133. ;; Record for a MidiShare Sequence
  134. ;;---------------------------------------------------------------------------------
  135.  
  136. (defrecord TMidiSeq
  137.   (first (:pointer TMidiEv))    ; first event
  138.   (last (:pointer TMidiEv))     ; last event
  139.   (undef1 :pointer)   
  140.   (undef2 :pointer) )  
  141.  
  142.  
  143. ;;---------------------------------------------------------------------------------
  144. ;; Record for a MidiShare input filter
  145. ;;---------------------------------------------------------------------------------
  146.  
  147. (defrecord TFilter
  148.   (port (string 63))     ; 256-bits
  149.   (evType (string 63))   ; 256-bits
  150.   (channel (string 1))   ;  16-bits
  151.   (unused (string 1)))   ;  16-bits
  152.  
  153.  
  154. ;;---------------------------------------------------------------------------------
  155. ;; Record for MidiShare SMPTE synchronisation informations
  156. ;;---------------------------------------------------------------------------------
  157.  
  158. (defrecord TSyncInfo
  159.   (time :longint)
  160.   (reenter :longint)
  161.   (syncMode :unsigned-short)
  162.   (syncLocked :byte)
  163.   (syncPort :byte)
  164.   (syncStart :longint)
  165.   (syncStop :longint)
  166.   (syncOffset :longint)
  167.   (syncSpeed :longint)
  168.   (syncBreaks :longint)
  169.   (syncFormat :short))
  170.  
  171.  
  172. ;;---------------------------------------------------------------------------------
  173. ;; Record for MidiShare SMPTE locations
  174. ;;---------------------------------------------------------------------------------
  175.  
  176. (defrecord TSmpteLocation
  177.   (format :short)
  178.   (hours :short)
  179.   (minutes :short)
  180.   (seconds :short)
  181.   (frames :short)
  182.   (fracs :short))
  183.  
  184.  
  185. ;;---------------------------------------------------------------------------------
  186. ;;---------------------------------------------------------------------------------
  187. ;;
  188. ;;         Macros for accessing MidiShare Events data structures
  189. ;;
  190. ;;---------------------------------------------------------------------------------
  191. ;;---------------------------------------------------------------------------------
  192.  
  193. ;;---------------------------------------------------------------------------------
  194. ;;                      Macros common to every type of event
  195. ;;---------------------------------------------------------------------------------
  196.  
  197. ;;................................................................................: link
  198. (defmacro link (e &optional (d nil d?))
  199. "read or set the link of an event"
  200.   (if d?
  201.     `(rset ,e :TMidiEv.link ,d)
  202.     `(rref ,e :TMidiEv.link)))
  203.  
  204. ;;................................................................................: date
  205. (defmacro date (e &optional d)
  206. "read or set the date of an event"
  207.   (if d
  208.     `(rset ,e :TMidiEv.date ,d)
  209.     `(rref ,e :TMidiEv.date)))
  210.  
  211. ;;................................................................................: type
  212. (defmacro type (e &optional v)
  213. "read or set the type of an event. Be careful in 
  214.  modifying the type of an event"
  215.   (if v
  216.     `(rset ,e :TMidiEv.evType ,v)
  217.     `(rref ,e :TMidiEv.evType)))
  218.  
  219. ;;................................................................................: ref
  220. (defmacro ref (e &optional v)
  221. "read or set the reference number of an event"
  222.   (if v
  223.     `(rset ,e :TMidiEv.ref ,v)
  224.     `(rref ,e :TMidiEv.ref)))
  225.  
  226. ;;................................................................................: port
  227. (defmacro port (e &optional v)
  228. "read or set the port number of an event"
  229.   (if v
  230.     `(rset ,e :TMidiEv.port ,v)
  231.     `(rref ,e :TMidiEv.port)))
  232.  
  233. ;;................................................................................: chan
  234. (defmacro chan (e &optional v)
  235. "read or set the chan number of an event"
  236.   (if v
  237.     `(rset ,e :TMidiEv.chan ,v)
  238.     `(rref ,e :TMidiEv.chan)))
  239.  
  240. ;;................................................................................: field
  241. (defmacro field (e &optional f v)
  242. "give the number of fields or read or set a particular field of an event"
  243.   (if f
  244.     (if v
  245.       `(midiSetField ,e ,f ,v)
  246.       `(midiGetField ,e ,f))
  247.     `(midiCountFields ,e)))
  248.  
  249. ;;................................................................................: fieldsList
  250. (defun fieldsList (e &optional (n 4))
  251. "collect all the fields of an event into a list"
  252.   (let (l)
  253.     (dotimes (i (min n (midicountfields e)))
  254.       (push (midigetfield e i) l))
  255.     (nreverse l)))
  256.  
  257.  
  258. ;;---------------------------------------------------------------------------------
  259. ;;                         Specific to typeNote events
  260. ;;---------------------------------------------------------------------------------
  261.  
  262. ;;................................................................................: pitch
  263. (defmacro pitch (e &optional v)
  264. "read or set the pitch of an event"
  265.   (if v
  266.     `(rset ,e :TMidiEv.pitch ,v)
  267.     `(rref ,e :TMidiEv.pitch)))
  268.  
  269. ;;................................................................................: vel
  270. (defmacro vel (e &optional v)
  271. "read or set the velocity of an event"
  272.   (if v
  273.     `(rset ,e :TMidiEv.vel ,v)
  274.     `(rref ,e :TMidiEv.vel)))
  275.  
  276. ;;................................................................................: dur
  277. (defmacro dur (e &optional v)
  278. "read or set the duration of an event"
  279.   (if v
  280.     `(rset ,e :TMidiEv.dur ,v)
  281.     `(rref ,e :TMidiEv.dur)))
  282.  
  283.  
  284. ;;---------------------------------------------------------------------------------
  285. ;;                        Specific to other types of events
  286. ;;---------------------------------------------------------------------------------
  287.  
  288. ;;................................................................................: linkSE
  289. (defmacro linkSE (e &optional (d nil d?))
  290. "read or set the link of an SEXevent "
  291.   (if d?
  292.     `(rset ,e :TMidiEv.linkSE ,d)
  293.     `(rref ,e :TMidiEv.linkSE)))
  294.  
  295. ;;................................................................................: linkST
  296. (defmacro linkST (e &optional (d nil d?))
  297.  "read or set the link of an STevent "
  298.   (if d?
  299.     `(rset ,e :TMidiEv.linkST ,d)
  300.     `(rref ,e :TMidiEv.linkST)))
  301.  
  302.  
  303. ;;................................................................................: kpress
  304. (defmacro kpress (e &optional v)
  305.   (if v
  306.     `(rset ,e :TMidiEv.vel ,v)
  307.     `(rref ,e :TMidiEv.vel)))
  308.  
  309.  
  310. ;;................................................................................: ctrl
  311. (defmacro ctrl (e &optional v)
  312.   (if v
  313.     `(midisetfield ,e 0 ,v)
  314.     `(midigetfield ,e 0)))
  315.  
  316.  
  317. ;;................................................................................: param
  318. (defmacro param (e &optional v)
  319.   (if v
  320.     `(midisetfield ,e 0 ,v)
  321.     `(midigetfield ,e 0)))
  322.  
  323.  
  324. ;;................................................................................: num
  325. (defmacro num (e &optional v)
  326.   (if v
  327.     `(midisetfield ,e 0 ,v)
  328.     `(midigetfield ,e 0)))
  329.  
  330.  
  331. ;;................................................................................: prefix
  332. (defmacro prefix (e &optional v)
  333.   (if v
  334.     `(midisetfield ,e 0 ,v)
  335.     `(midigetfield ,e 0)))
  336.  
  337.  
  338. ;;................................................................................: tempo
  339. (defmacro tempo (e &optional v)
  340.   (if v
  341.     `(midisetfield ,e 0 ,v)
  342.     `(midigetfield ,e 0)))
  343.  
  344.  
  345. ;;................................................................................: seconds
  346. (defmacro seconds (e &optional v)
  347.   (if v
  348.     `(midisetfield ,e 0 ,v)
  349.     `(midigetfield ,e 0)))
  350.  
  351.  
  352. ;;................................................................................: subframes
  353. (defmacro subframes (e &optional v)
  354.   (if v
  355.     `(midisetfield ,e 1 ,v)
  356.     `(midigetfield ,e 1)))
  357.  
  358.  
  359. ;;................................................................................: val
  360. (defmacro val (e &optional v)
  361.   (if v
  362.     `(midisetfield ,e 1 ,v)
  363.     `(midigetfield ,e 1)))
  364.  
  365.  
  366. ;;................................................................................: pgm
  367. (defmacro pgm (e &optional v)
  368.   (if v
  369.     `(rset ,e :TMidiEv.pitch ,v)
  370.     `(rref ,e :TMidiEv.pitch)))
  371.  
  372.  
  373. ;;................................................................................: bend
  374. (defmacro bend (e &optional v)
  375.   "read or set the bend value of an event"
  376.   (if v
  377.     `(multiple-value-bind (ms7b ls7b) (floor (+ ,v 8192) 128)
  378.        (rset ,e :TMidiEv.pitch ls7b)
  379.        (rset ,e :TMidiEv.vel ms7b))
  380.     `(- (+ (rref ,e :TMidiEv.pitch) (* 128 (rref ,e :TMidiEv.vel))) 8192)))
  381.  
  382.  
  383. ;;................................................................................: clk
  384. (defmacro clk (e &optional v)
  385.   (if v
  386.     `(multiple-value-bind (ms7b ls7b) (floor (round (/ ,v 6)) 128)
  387.        (rset ,e :TMidiEv.pitch ls7b)
  388.        (rset ,e :TMidiEv.vel ms7b))
  389.     `(* 6 (+ (pitch ,e) (* 128 (vel ,e)))) ))
  390.  
  391.  
  392. ;;................................................................................: song
  393. (defmacro song (e &optional v)
  394.   (if v
  395.     `(rset ,e :TMidiEv.pitch ,v)
  396.     `(rref ,e :TMidiEv.pitch)))
  397.  
  398.  
  399. ;;................................................................................: fields
  400. (defmacro fields (e &optional v)
  401.   (if v
  402.     `(let ((e ,e)) (mapc #'(lambda (f) (midiaddfield e f)) ,v))
  403.     `(let (l (e ,e))  (dotimes (i (midicountfields e)) (push (midigetfield e i) l)) (nreverse l)) ))
  404.  
  405.  
  406. ;;................................................................................: text
  407. (defmacro text (e &optional s)
  408.   (if s
  409.     `(fields ,e (map 'list #'char-code ,s))
  410.     `(map 'string #'character (fields ,e)) ))
  411.  
  412.  
  413. ;;................................................................................: fmsg
  414. (defmacro fmsg (e &optional v)
  415.   (if v
  416.     `(rset ,e :TMidiEv.pitch ,v)
  417.     `(rref ,e :TMidiEv.pitch)))
  418.  
  419. ;;................................................................................: fcount
  420. (defmacro fcount (e &optional v)
  421.   (if v
  422.     `(rset ,e :TMidiEv.vel ,v)
  423.     `(rref ,e :TMidiEv.vel)))
  424.  
  425. ;;................................................................................: tsnum
  426. (defmacro tsnum (e &optional v)
  427.   (if v
  428.     `(midisetfield ,e 0 ,v)
  429.     `(midigetfield ,e 0)))
  430.  
  431.  
  432. ;;................................................................................: tsdenom
  433. (defmacro tsdenom (e &optional v)
  434.   (if v
  435.     `(midisetfield ,e 1 ,v)
  436.     `(midigetfield ,e 1)))
  437.  
  438.  
  439. ;;................................................................................: tsclick
  440. (defmacro tsclick (e &optional v)
  441.   (if v
  442.     `(midisetfield ,e 2 ,v)
  443.     `(midigetfield ,e 2)))
  444.  
  445.  
  446. ;;................................................................................: tsquarter
  447. (defmacro tsquarter (e &optional v)
  448.   (if v
  449.     `(midisetfield ,e 3 ,v)
  450.     `(midigetfield ,e 3)))
  451.  
  452. ;;................................................................................: alteration
  453. (defmacro alteration (e &optional v)
  454.   (if v
  455.     `(midisetfield ,e 0 ,v)
  456.     `(midigetfield ,e 0)))
  457.  
  458. ;;................................................................................: minor-scale
  459. (defmacro minor-scale (e &optional v)
  460.   (if v
  461.     `(midisetfield ,e 1 (if ,v 1 0))
  462.     `(= 1 (midigetfield ,e 1))))
  463.  
  464. ;;................................................................................: info
  465. (defmacro info (e &optional d)
  466. "read or set the info of an event"
  467.   (if d
  468.     `(rset ,e :TMidiEv.info ,d)
  469.     `(rref ,e :TMidiEv.info)))
  470.  
  471.  
  472.  
  473. ;;---------------------------------------------------------------------------------
  474. ;;---------------------------------------------------------------------------------
  475. ;;
  476. ;;         Macros for accessing MidiShare Sequences data structures
  477. ;;
  478. ;;---------------------------------------------------------------------------------
  479. ;;---------------------------------------------------------------------------------
  480.  
  481. ;;................................................................................: firstEv
  482. (defmacro firstEv (s &optional (e nil e?))
  483. "read or set the first event of a sequence"
  484.   (if e?
  485.     `(rset ,s :TMidiSeq.first ,e)
  486.     `(rref ,s :TMidiSeq.first)))
  487.  
  488. ;;................................................................................: lastEv
  489. (defmacro lastEv (s &optional (e nil e?))
  490. "read or set the last event of a sequence"
  491.   (if e?
  492.     `(rset ,s :TMidiSeq.last ,e)
  493.     `(rref ,s :TMidiSeq.last)))
  494.  
  495.  
  496. ;;---------------------------------------------------------------------------------
  497. ;;---------------------------------------------------------------------------------
  498. ;;
  499. ;;         Macros for accessing MidiShare Filters
  500. ;;
  501. ;;---------------------------------------------------------------------------------
  502. ;;---------------------------------------------------------------------------------
  503.  
  504. ;;................................................................................: FilterBit
  505. (defun FilterBit (p n &optional (val nil val?))
  506.   (if val?
  507.     (%put-byte p (if val 
  508.                    (logior (%get-byte p (ash n -3)) (ash 1 (logand n 7)))
  509.                    (logandc2 (%get-byte p (ash n -3)) (ash 1 (logand n 7))) )
  510.                (ash n -3))
  511.     (logbitp (logand n 7) (%get-byte p (ash n -3)))))
  512.  
  513. ;;................................................................................: AcceptPort
  514. (defmacro AcceptPort (f p &rest s)
  515.   `(filterBit ,f ,p ,@s))
  516.  
  517. ;;................................................................................: AcceptType
  518. (defmacro AcceptType (f p &rest s)
  519.   `(filterBit (%inc-ptr ,f 32) ,p ,@s))
  520.  
  521. ;;................................................................................: AcceptChan
  522. (defmacro AcceptChan (f p &rest s)
  523.   `(filterBit (%inc-ptr ,f 64) ,p ,@s))
  524.  
  525.  
  526.  
  527.  
  528.  
  529. ;;---------------------------------------------------------------------------------
  530. ;;---------------------------------------------------------------------------------
  531. ;;
  532. ;;                 MidiShare Constant Definitions
  533. ;;
  534. ;;---------------------------------------------------------------------------------
  535. ;;---------------------------------------------------------------------------------
  536.  
  537.  
  538. ;; Constant definition for every type of MidiShare events
  539.  
  540. (defconstant typeNote 0          "a note with pitch, velocity and duration")
  541. (defconstant typeKeyOn 1         "a key on with pitch and velocity")
  542. (defconstant typeKeyOff 2        "a key off with pitch and velocity")
  543. (defconstant typeKeyPress 3      "a key pressure with pitch and pressure value")
  544. (defconstant typeCtrlChange 4    "a control change with control number and control value")
  545. (defconstant typeProgChange 5    "a program change with program number")
  546. (defconstant typeChanPress 6     "a channel pressure with pressure value")
  547. (defconstant typePitchWheel 7    "a pitch bender with lsb and msb of the 14-bit value")
  548. (defconstant typePitchBend 7     "a pitch bender with lsb and msb of the 14-bit value")
  549. (defconstant typeSongPos 8       "a song position with lsb and msb of the 14-bit position")
  550. (defconstant typeSongSel 9       "a song selection with a song number")
  551. (defconstant typeClock 10        "a clock request (no argument)")
  552. (defconstant typeStart 11        "a start request (no argument)")
  553. (defconstant typeContinue 12     "a continue request (no argument)")
  554. (defconstant typeStop 13         "a stop request (no argument)")
  555. (defconstant typeTune 14         "a tune request (no argument)")
  556. (defconstant typeActiveSens 15   "an active sensing code (no argument)")
  557. (defconstant typeReset 16        "a reset request (no argument)")
  558. (defconstant typeSysEx 17        "a system exclusive with any number of data bytes. Leading $F0 and tailing $F7 are automatically supplied by MidiShare and MUST NOT be included by the user")
  559. (defconstant typeStream 18       "a special event with any number of data and status bytes sended without any processing")
  560. (defconstant typePrivate 19      "a private event for internal use with 4 32-bits arguments")
  561. (defconstant typeProcess 128     "an interrupt level task with a function adress and 3 32-bits arguments")
  562. (defconstant typeDProcess 129    "a foreground level task with a function adress and 3 32-bits arguments")
  563. (defconstant typeQFrame 130      "a quarter frame message with a type from 0 to 7 and a value")
  564.  
  565.  
  566. (defconstant typeCtrl14b    131)
  567. (defconstant typeNonRegParam    132)
  568. (defconstant typeRegParam    133)
  569.  
  570. (defconstant typeSeqNum        134)
  571. (defconstant typeText        135)
  572. (defconstant typeCopyright    136)
  573. (defconstant typeSeqName    137)
  574. (defconstant typeInstrName    138)
  575. (defconstant typeLyric        139)
  576. (defconstant typeMarker        140)
  577. (defconstant typeCuePoint    141)
  578. (defconstant typeChanPrefix    142)
  579. (defconstant typeEndTrack    143)
  580. (defconstant typeTempo        144)
  581. (defconstant typeSMPTEOffset    145)
  582.  
  583. (defconstant typeTimeSign    146)
  584. (defconstant typeKeySign    147)
  585. (defconstant typeSpecific    148)
  586.  
  587. (defconstant typeReserved 149    "events reserved for futur use")
  588. (defconstant typedead 255        "a dead task. Used by MidiShare to forget and inactivate typeProcess and typeDProcess tasks")
  589.  
  590.  
  591. ;; Constant definition for every MidiShare error code
  592.  
  593. (defconstant MIDIerrSpace -1     "too many applications")
  594. (defconstant MIDIerrRefNum -2     "bad reference number")
  595. (defconstant MIDIerrBadType -3   "bad event type")
  596. (defconstant MIDIerrIndex -4     "bad index")
  597.  
  598.  
  599. ;; Constant definition for the Macintosh serial ports
  600.  
  601. (defconstant ModemPort 0     "Macintosh modem port")
  602. (defconstant PrinterPort 1     "Macintosh printer port")
  603.  
  604.  
  605. ;; Constant definition for the synchronisation modes
  606.  
  607. (defconstant MidiExternalSync #x8000     "Bit-15 set for external synchronisation")
  608. (defconstant MidiSyncAnyPort #x4000     "Bit-14 set for synchronisation on any port")
  609.  
  610.  
  611. ;; Constant definition for SMPTE frame format
  612.  
  613. (defconstant smpte24fr 0         "24 frame/sec")
  614. (defconstant smpte25fr 1         "25 frame/sec")
  615. (defconstant smpte29fr 2         "29 frame/sec (30 drop frame)")
  616. (defconstant smpte30fr 3         "30 frame/sec")
  617.  
  618.  
  619. ;; Constant definition for MidiShare world changes
  620.  
  621. (defconstant MIDIOpenAppl 1      "an application was opened")
  622. (defconstant MIDICloseAppl 2     "an application was closed")
  623. (defconstant MIDIChgName 3       "an application name was changed")
  624. (defconstant MIDIChgConnect 4    "a connection was changed")
  625. (defconstant MIDIOpenModem 5     "Modem port was opened")
  626. (defconstant MIDICloseModem 6    "Modem port was closed")
  627. (defconstant MIDIOpenPrinter 7   "Printer port was opened")
  628. (defconstant MIDIClosePrinter 8  "Printer port was closed")
  629. (defconstant MIDISyncStart 9     "SMPTE synchronisation just start")
  630. (defconstant MIDISyncStop 10     "SMPTE synchronisation just stop")
  631.  
  632.  
  633.  
  634.  
  635.  
  636. ;;---------------------------------------------------------------------------------
  637. ;;---------------------------------------------------------------------------------
  638. ;;
  639. ;;                 MidiShare Entry Points
  640. ;;
  641. ;;---------------------------------------------------------------------------------
  642. ;;---------------------------------------------------------------------------------
  643.  
  644. ;; Interface description for a MidiShare PROCEDURE 
  645. ;; with a word and a pointer parameter
  646. ;;  (ff-call *midiShare* :word <arg1> :ptr <arg2> :d0 <MidiShare routine #>)
  647. ;;
  648. ;; Interface description for a MidiShare FUNCTION (previous to MCL PPC 3.9)
  649. ;; with a word and a pointer parameter and a pointer result
  650. ;;  (ff-call *midiShare*  :ptr (%null-ptr) :word <arg1> :ptr <arg2> :d0 <MidiShare routine #> :ptr)
  651. ;;
  652. ;; Interface description for a MidiShare FUNCTION (with MCL PPC 3.9) 
  653. ;; with a word and a pointer parameter and a pointer result
  654. ;;  (ff-call *midiShare* :word <arg1> :ptr <arg2> :d0 <MidiShare routine #> :ptr)
  655. ;;
  656.  
  657.  
  658. ;; Entry point of MidiShare (setup at boot time by the "MidiShare" init)
  659.  
  660. (defvar *midiShare*)
  661.  
  662. ;;---------------------------------------------------------------------------------
  663. ;;            To Know about MidiShare and Active Sessions
  664. ;;---------------------------------------------------------------------------------
  665.  
  666. ;;................................................................................: MidiShare
  667. (defun MidiShare ()
  668. "returns true if MidiShare is installed"
  669.   (and (= (%get-word *midiShare*) #xD080)
  670.        (= (%get-word *midiShare* 2) #xD080)))
  671.  
  672. ;;................................................................................: MidiGetVersion
  673. (defmacro MidiGetVersion ()
  674. "Give MidiShare version as a fixnum. For example 131 as result, means : version 1.31"
  675.   `(ff-call *midiShare* :d0 0 :word))
  676.  
  677. ;;................................................................................: MidiCountAppls
  678. (defmacro MidiCountAppls ()
  679. "Give the number of MidiShare applications currently opened"
  680.   `(ff-call *midiShare* :d0 1 :word))
  681.  
  682. ;;................................................................................: MidiGetIndAppl
  683. (defmacro MidiGetIndAppl (index)
  684. "Give the reference number of a MidiShare application from its index, a fixnum
  685.  between 1 and (MidiCountAppls)"
  686.   `(%%unsigned-to-signed-word (ff-call *midiShare* :word ,index :d0 2 :word)))
  687.  
  688. ;;................................................................................: MidiGetNamedAppl
  689. (defmacro MidiGetNamedAppl (name)
  690. "Give the reference number of a MidiShare application from its name"
  691.   `(with-pstrs ((s ,name))
  692.     (%%unsigned-to-signed-word (ff-call *midiShare* :ptr s :d0 3 :word))))
  693.  
  694. ;;---------------------------------------------------------------------------------
  695. ;;            To Open and Close a MidiShare session
  696. ;;---------------------------------------------------------------------------------
  697.  
  698. ;;................................................................................: MidiOpen
  699. (defmacro MidiOpen (name)
  700. "Open a new MidiShare application, with name name. Give a unique reference number."
  701.   `(with-pstrs ((s ,name))
  702.     (%%unsigned-to-signed-word (ff-call *midiShare* :ptr s :d0 4 :word))))
  703.  
  704. ;;................................................................................: MidiClose
  705. (defmacro MidiClose (refNum)
  706. "Close an opened MidiShare application from its reference number"
  707.   `(ff-call *midiShare* :word ,refNum :d0 5))
  708.  
  709.  
  710. ;;---------------------------------------------------------------------------------
  711. ;;            To Configure a MidiShare session
  712. ;;---------------------------------------------------------------------------------
  713.  
  714. ;;................................................................................: MidiGetName
  715. (defmacro MidiGetName (refNum)
  716. "Give the name of a MidiShare application from its reference number"
  717.     `(%%get-string (ff-call *midiShare* :word ,refNum :d0 6 :ptr)))
  718.  
  719. ;;................................................................................: MidiSetName
  720. (defmacro MidiSetName (refNum name)
  721. "Change the name of a MidiShare application"
  722.   `(with-pstrs ((s ,name))
  723.     (ff-call *midiShare* :word ,refNum :ptr s :d0 7 )))
  724.  
  725. ;;................................................................................: MidiGetInfo
  726. (defmacro MidiGetInfo (refNum)
  727. "Give the 32-bits user defined content of the info field of a MidiShare application. 
  728.  Analogous to window's refcon."
  729.   `(ff-call *midiShare* :word ,refNum :d0 8 :ptr))
  730.  
  731. ;;................................................................................: MidiSetInfo
  732. (defmacro MidiSetInfo (refNum p)
  733. "Set the 32-bits user defined content of the info field of a MidiShare application. 
  734.  Analogous to window's refcon."
  735.   `(ff-call *midiShare* :word ,refNum :ptr ,p :d0 9))
  736.  
  737. ;;................................................................................: MidiGetFilter
  738. (defmacro MidiGetFilter (refNum)
  739. "Give a pointer to the input filter record of a MidiShare application. 
  740.  Give NIL if no filter is installed"
  741.   `(ff-call *midiShare* :word ,refNum :d0 10 :ptr))
  742.  
  743. ;;................................................................................: MidiSetFilter
  744. (defmacro MidiSetFilter (refNum p)
  745. "Install an input filter. The argument p is a pointer to a filter record."
  746.   `(ff-call *midiShare* :word ,refNum :ptr ,p :d0 11))
  747.  
  748. ;;................................................................................: MidiGetRcvAlarm
  749. (defmacro MidiGetRcvAlarm (refNum)
  750. "Get the adress of the receive alarm"
  751.   `(ff-call *midiShare* :word ,refNum :d0 #x0C :ptr))
  752.  
  753. ;;................................................................................: MidiSetRcvAlarm
  754. (defmacro MidiSetRcvAlarm (refNum alarm)
  755. "Install a receive alarm"
  756.   `(ff-call *midiShare* :word ,refNum :ptr ,alarm :d0 #x0D))
  757.  
  758. ;;................................................................................: MidiGetApplAlarm
  759. (defmacro MidiGetApplAlarm (refNum)
  760. "Get the adress of the context alarm"
  761.   `(ff-call *midiShare* :word ,refNum :d0 #x0E :ptr))
  762.  
  763. ;;................................................................................: MidiSetApplAlarm
  764. (defmacro MidiSetApplAlarm (refNum alarm)
  765. "Install a context alarm"
  766.   `(ff-call *midiShare* :word ,refNum :ptr ,alarm :d0 #x0F))
  767.  
  768. ;;---------------------------------------------------------------------------------
  769. ;;            To Manage MidiShare IAC and Midi Ports
  770. ;;---------------------------------------------------------------------------------
  771.  
  772. ;;................................................................................: MidiConnect
  773. (defmacro MidiConnect (src dst state)
  774. "Connect or disconnect two MidiShare applications"
  775.   `(ff-call *midiShare* :word ,src :word ,dst :word (if ,state -1 0) :d0 #x10))
  776.  
  777. ;;................................................................................: MidiIsConnected
  778. (defmacro MidiIsConnected (src dst)
  779. "Test if two MidiShare applications are connected"
  780.   `(not (eq 0 (ff-call *midiShare* :word ,src :word ,dst :d0 #x11 :word))))
  781.  
  782. ;;................................................................................: MidiGetPortState
  783. (defmacro MidiGetPortState (port)
  784. "Give the state : open or closed, of a MidiPort"
  785.   `(not (eq 0 (%%word-high-byte (ff-call *midiShare* :word ,port :d0 #x12 :word)))))
  786.  
  787. ;;................................................................................: MidiSetPortState
  788. (defmacro MidiSetPortState (port state)
  789. "Open or close a MidiPort"
  790.   `(ff-call *midiShare* :word ,port :word (if ,state -1 0) :d0 #x13))
  791.  
  792. ;;---------------------------------------------------------------------------------
  793. ;;            To Manage MidiShare events
  794. ;;---------------------------------------------------------------------------------
  795.  
  796. ;;................................................................................: MidiFreeSpace
  797. (defmacro MidiFreeSpace ()
  798. "Amount of free MidiShare cells"
  799.   `(ff-call *midiShare* :d0 #x14 :long))
  800.  
  801. ;;................................................................................: MidiNewEv
  802. (defmacro MidiNewEv (typeNum)
  803. "Allocate a new MidiEvent"
  804.   `(ff-call *midiShare* :word ,typeNum :d0 #x15 :ptr))
  805.  
  806. ;;................................................................................: MidiCopyEv
  807. (defmacro MidiCopyEv (ev)
  808. "Duplicate a MidiEvent"
  809.   `(ff-call *midiShare* :ptr ,ev :d0 #x16 :ptr))
  810.  
  811. ;;................................................................................: MidiFreeEv
  812. (defmacro MidiFreeEv (ev)
  813. "Free a MidiEvent"
  814.   `(ff-call *midiShare* :ptr ,ev :d0 #x17))
  815.  
  816.  
  817. ;;................................................................................: MidiSetField
  818. (defmacro MidiSetField (ev field val)
  819. "Set a field of a MidiEvent"
  820.   `(ff-call *midiShare* :ptr ,ev :long ,field :long ,val :d0 #x3A))
  821.  
  822. ;;................................................................................: MidiGetField
  823. (defmacro MidiGetField (ev field)
  824. "Get a field of a MidiEvent"
  825.   `(ff-call *midiShare* :ptr ,ev :long ,field :d0 #x3B :long))
  826.  
  827. ;;................................................................................: MidiAddField
  828. (defmacro MidiAddField (ev val)
  829. "Append a field to a MidiEvent (only for sysex and stream)"
  830.   `(ff-call *midiShare* :ptr ,ev :long ,val :d0 #x1A))
  831.  
  832. ;;................................................................................: MidiCountFields
  833. (defmacro MidiCountFields (ev)
  834. "The number of fields of a MidiEvent"
  835.   `(ff-call *midiShare* :ptr ,ev :d0 #x3C :long))
  836.  
  837. ;;---------------------------------------------------------------------------------
  838. ;;            To Manage MidiShare Sequences
  839. ;;---------------------------------------------------------------------------------
  840.  
  841. ;;................................................................................: MidiNewSeq
  842. (defmacro MidiNewSeq ()
  843. "Allocate an empty sequence"
  844.   `(ff-call *midiShare* :d0 #x1D :ptr))
  845.  
  846. ;;................................................................................: MidiAddSeq
  847. (defmacro MidiAddSeq (seq ev)
  848. "Add an event to a sequence"
  849.   `(ff-call *midiShare* :ptr ,seq :ptr ,ev :d0 #x1E))
  850.  
  851. ;;................................................................................: MidiFreeSeq
  852. (defmacro MidiFreeSeq (seq)
  853. "Free a sequence and its content"
  854.   `(ff-call *midiShare* :ptr ,seq :d0 #x1F))
  855.  
  856. ;;................................................................................: MidiClearSeq
  857. (defmacro MidiClearSeq (seq)
  858. "Free only the content of a sequence. The sequence become empty"
  859.   `(ff-call *midiShare* :ptr ,seq :d0 #x20))
  860.  
  861. ;;................................................................................: MidiApplySeq
  862. (defmacro MidiApplySeq (seq proc)
  863. "Call a function for every events of a sequence"
  864.   `(ff-call *midiShare* :ptr ,seq :ptr ,proc :d0 #x21))
  865.  
  866. ;;---------------------------------------------------------------------------------
  867. ;;                   MidiShare Time
  868. ;;---------------------------------------------------------------------------------
  869.  
  870. ;;................................................................................: MidiGetTime
  871. (defmacro MidiGetTime ()
  872. "give the current time"
  873.   `(ff-call *midiShare* :d0 #x22 :long))
  874.  
  875. ;;---------------------------------------------------------------------------------
  876. ;;                To Send MidiShare events
  877. ;;---------------------------------------------------------------------------------
  878.  
  879. ;;................................................................................: MidiSendIm
  880. (defmacro MidiSendIm (refNum ev)
  881. "send an event now"
  882.   `(ff-call *midiShare* :word ,refNum :ptr ,ev :d0 #x23))
  883.  
  884. ;;................................................................................: MidiSend
  885. (defmacro MidiSend (refNum ev)
  886. "send an event using its own date"
  887.   `(ff-call *midiShare* :word ,refNum :ptr ,ev :d0 #x24))
  888.  
  889. ;;................................................................................: MidiSendAt
  890. (defmacro MidiSendAt (refNum ev date)
  891. "send an event at date <date>"
  892.   `(ff-call *midiShare* :word ,refNum :ptr ,ev :long ,date :d0 #x25))
  893.  
  894. ;;---------------------------------------------------------------------------------
  895. ;;                            To Receive MidiShare Events
  896. ;;---------------------------------------------------------------------------------
  897.  
  898. ;;................................................................................: MidiCountEvs
  899. (defmacro MidiCountEvs (refNum)
  900. "Give the number of events waiting in the reception fifo"
  901.   `(ff-call *midiShare* :word ,refNum :d0 #x26 :long))
  902.  
  903. ;;................................................................................: MidiGetEv
  904. (defmacro MidiGetEv (refNum)
  905. "Read an event from the reception fifo"
  906.   `(ff-call *midiShare* :word ,refNum :d0 #x27 :ptr))
  907.  
  908. ;;................................................................................: MidiAvailEv
  909. (defmacro MidiAvailEv (refNum)
  910. "Get a pointer to the first event in the reception fifo without removing it"
  911.   `(ff-call *midiShare* :word ,refNum :d0 #x28 :ptr))
  912.  
  913. ;;................................................................................: MidiFlushEvs
  914. (defmacro MidiFlushEvs (refNum)
  915. "Delete all the events waiting in the reception fifo"
  916.   `(ff-call *midiShare* :word ,refNum :d0 #x29))
  917.  
  918. ;;---------------------------------------------------------------------------------
  919. ;;                             To access shared data
  920. ;;---------------------------------------------------------------------------------
  921.  
  922. ;;................................................................................: MidiReadSync
  923. (defmacro MidiReadSync (adrMem)
  924. "Read and clear a memory address (not-interruptible)"
  925.   `(ff-call *midiShare* :ptr ,adrMem :d0 #x2A :ptr))
  926.  
  927. ;;................................................................................: MidiWriteSync
  928. (defmacro MidiWriteSync (adrMem val)
  929. "write if nil into a memory address (not-interruptible)"
  930.   `(ff-call *midiShare* :ptr ,adrMem :ptr ,val :d0 #x2B :ptr))
  931.  
  932. ;;---------------------------------------------------------------------------------
  933. ;;                               Realtime Tasks
  934. ;;---------------------------------------------------------------------------------
  935.  
  936. ;;................................................................................: MidiCall
  937. (defmacro MidiCall (proc date refNum arg1 arg2 arg3)
  938. "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>"
  939.   `(ff-call *midiShare* :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2C))
  940.  
  941. ;;................................................................................: MidiTask
  942. (defmacro MidiTask (proc date refNum arg1 arg2 arg3)
  943. "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>. 
  944.  Return a pointer to the corresponding typeProcess event"
  945.   `(ff-call *midiShare* :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2D :ptr))
  946.  
  947. ;;................................................................................: MidiDTask
  948. (defmacro MidiDTask (proc date refNum arg1 arg2 arg3)
  949. "Call the routine <proc> at date <date> with arguments <arg1> <arg2> <arg3>. 
  950.  Return a pointer to the corresponding typeDProcess event"
  951.   `(ff-call *midiShare* :ptr ,proc :long ,date :word ,refNum :long ,arg1 :long ,arg2 :long ,arg3 :d0 #x2E :ptr))
  952.  
  953. ;;................................................................................: MidiForgetTaskHdl
  954. (defmacro MidiForgetTaskHdl (thdl)
  955. "Forget a previously scheduled typeProcess or typeDProcess event created by MidiTask or MidiDTask"
  956.   `(ff-call *midiShare* :ptr ,thdl :d0 #x2F))
  957.  
  958. ;;................................................................................: MidiForgetTask
  959. (defmacro MidiForgetTask (ev)
  960. "Forget a previously scheduled typeProcess or typeDProcess event created by MidiTask or MidiDTask"
  961.   `(without-interrupts 
  962.     (%stack-block ((taskptr 4))
  963.       (%setf-macptr taskptr ,ev) (midiforgetTaskHdl taskptr))))
  964.  
  965. ;;................................................................................: MidiCountDTasks
  966. (defmacro MidiCountDTasks (refNum)
  967. "Give the number of typeDProcess events waiting"
  968.   `(ff-call *midiShare* :word ,refNum :d0 #x30 :long))
  969.  
  970. ;;................................................................................: MidiFlushDTasks
  971. (defmacro MidiFlushDTasks (refNum)
  972. "Remove all the typeDProcess events waiting"
  973.   `(ff-call *midiShare* :word ,refNum :d0 #x31))
  974.  
  975. ;;................................................................................: MidiExec1DTask
  976. (defmacro MidiExec1DTask (refNum)
  977. "Call the next typeDProcess waiting"
  978.   `(ff-call *midiShare* :word ,refNum :d0 #x32))
  979.  
  980. ;;---------------------------------------------------------------------------------
  981. ;;                        Low Level MidiShare Memory Management
  982. ;;---------------------------------------------------------------------------------
  983.  
  984. ;;................................................................................: MidiNewCell
  985. (defmacro MidiNewCell ()
  986. "Allocate a basic Cell"
  987.   `(ff-call *midiShare* :d0 #x33 :ptr))
  988.  
  989. ;;................................................................................: MidiFreeCell
  990. (defmacro MidiFreeCell (cell)
  991. "Delete a basic Cell"
  992.   `(ff-call *midiShare* :ptr ,cell :d0 #x34))
  993.  
  994. ;;................................................................................: MidiTotalSpace
  995. (defmacro MidiTotalSpace ()
  996. "Total amount of Cells"
  997.   `(ff-call *midiShare* :d0 #x35 :long))
  998.  
  999. ;;................................................................................: MidiGrowSpace
  1000. (defmacro MidiGrowSpace (n)
  1001. "Total amount of Cells"
  1002.   `(ff-call *midiShare* :long ,n :d0 #x36 :long))
  1003.  
  1004.  
  1005. ;;---------------------------------------------------------------------------------
  1006. ;;                        SMPTE Synchronisation functions
  1007. ;;---------------------------------------------------------------------------------
  1008.  
  1009. ;;................................................................................: MidiGetSyncInfo
  1010. (defmacro MidiGetSyncInfo (syncInfo)
  1011. "Fill syncInfo with current synchronisation informations"
  1012.   `(ff-call *midiShare* :ptr ,syncInfo :d0 #x38))
  1013.  
  1014. ;;................................................................................: MidiSetSyncMode
  1015. (defmacro MidiSetSyncMode (mode)
  1016. "set the MidiShare synchroniation mode"
  1017.   `(ff-call *midiShare* :word ,mode :d0 #x39))
  1018.  
  1019. ;;................................................................................: MidiGetExtTime
  1020. (defmacro MidiGetExtTime ()
  1021. "give the current external time"
  1022.   `(ff-call *midiShare* :d0 #x3D :long))
  1023.  
  1024. ;;................................................................................: MidiInt2ExtTime
  1025. (defmacro MidiInt2ExtTime (time)
  1026. "convert internal time to external time"
  1027.   `(ff-call *midiShare* :long ,time :d0 #x3E :long))
  1028.  
  1029. ;;................................................................................: MidiExt2IntTime
  1030. (defmacro MidiExt2IntTime (time)
  1031. "convert internal time to external time"
  1032.   `(ff-call *midiShare* :long ,time :d0 #x3F :long))
  1033.  
  1034. ;;................................................................................: MidiTime2Smpte
  1035. (defmacro MidiTime2Smpte (time format smpteLocation)
  1036. "convert time to Smpte location"
  1037.   `(ff-call *midiShare* :long ,time :word ,format :ptr ,smpteLocation :d0 #x40))
  1038.  
  1039. ;;................................................................................: MidiSmpte2Time
  1040. (defmacro MidiSmpte2Time (smpteLocation)
  1041. "convert time to Smpte location"
  1042.   `(ff-call *midiShare* :ptr ,smpteLocation :d0 #x41 :long))
  1043.  
  1044.  
  1045.  
  1046. ;;---------------------------------------------------------------------------------
  1047. ;;---------------------------------------------------------------------------------
  1048. ;;
  1049. ;;             To Install and Remove the MidiShare Interface
  1050. ;;
  1051. ;;---------------------------------------------------------------------------------
  1052. ;;---------------------------------------------------------------------------------
  1053.  
  1054.  
  1055. ;;---------------------------------------------------------------------------------
  1056. ;;                 To Add Startup and Quit Actions
  1057. ;;---------------------------------------------------------------------------------
  1058.  
  1059. ;;................................................................................: add-startup-action
  1060. (defmethod add-startup-action ((foo function))
  1061.   (pushnew foo *lisp-startup-functions*))
  1062.  
  1063. ;;................................................................................: add-quit-action
  1064. (defmethod add-quit-action ((foo function))
  1065.   (pushnew foo *lisp-cleanup-functions*))
  1066.  
  1067.  
  1068. ;;---------------------------------------------------------------------------------
  1069. ;;              MidiShare Startup and Quit Actions
  1070. ;;---------------------------------------------------------------------------------
  1071.  
  1072. ;;................................................................................: install-midishare-interface
  1073. (defun install-midishare-interface ()
  1074.   (setq *midiShare* (%get-ptr (%int-to-ptr #xB8)))
  1075.   (unless (midishare) (error "MidiShare not installed")))
  1076.  
  1077. ;;................................................................................: remove-midishare-interface
  1078. (defun remove-midishare-interface ()
  1079.   (setq *midiShare* nil))
  1080.  
  1081. ;;---------------------------------------------------------------------------------
  1082. ;;                  **Evaluate this**
  1083. ;;---------------------------------------------------------------------------------
  1084.  
  1085. (eval-when (:load-toplevel :execute)
  1086.   (add-startup-action #'install-midishare-interface)
  1087.   (add-quit-action #'remove-midishare-interface)
  1088.   (install-midishare-interface))
  1089.